﻿using System;
using Sunny.Core.Exception;

namespace Sunny.Core.DefinedData
{
    [Serializable]
    public struct SKey : IComparable<SKey>
    {
        private readonly long? _key;

        public SKey(long? value)
        {
            this._key = value;
        }

        #region IComparable<SKey> Members

        public int CompareTo(SKey other)
        {
            if (_key.HasValue)
            {
                return _key.Value.CompareTo(other._key);
            }
            else if (!other._key.HasValue)
            {
                return 0;
            }
            else
            {
                return -1;
            }
        }

        #endregion

        #region Implicit Operator SKey

        public static implicit operator SKey(string value)
        {
            if (String.IsNullOrEmpty(value))
            {
                return new SKey(null);
            }
            else
            {
                long tempKey;
                if (long.TryParse(value, out tempKey))
                {
                    return new SKey(tempKey);
                }
                else
                {
                    throw new DefinedDataException("The source value is " + value);
                }
            }
        }

        public static implicit operator SKey(long? value)
        {
            return new SKey(value);
        }

        #endregion

        #region Implicit Operator Other

        public static implicit operator string(SKey value)
        {
            return value._key.ToString();
        }

        public static implicit operator long(SKey value)
        {
            if (value._key.HasValue)
            {
                return value._key.Value;
            }
            else
            {
                throw new DefinedDataException("The key is null, can't convert to long.");
            }
        }

        public static implicit operator long?(SKey value)
        {
            return value._key;
        }

        #endregion

        #region Implicit Operator

        public static bool operator ==(SKey x, SKey y)
        {
            return x._key == y._key;
        }

        public static bool operator !=(SKey x, SKey y)
        {
            return x._key != y._key;
        }

        #endregion

        public override string ToString()
        {
            return _key.ToString();
        }

        /// <summary>
        /// Return the value is null
        /// </summary>
        /// <returns>The value is null</returns>
        public bool IsNull()
        {
            return !_key.HasValue;
        }

        public bool Equals(SKey obj)
        {
            return obj._key.Equals(_key);
        }

        public override bool Equals(object obj)
        {
            if (obj.GetType() != typeof (SKey)) return false;
            return Equals((SKey) obj);
        }

        public override int GetHashCode()
        {
            return (_key.HasValue ? _key.Value.GetHashCode() : 0);
        }
    }
}
